// 线程池
#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include "Thread.hpp"
#include "LockGuard.hpp"

using namespace std;

//创建线程的数量
const static int num = 5;

// T类型是线程池任务队列中的任务类型
template <typename T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    // 构造函数私有化，设计单例模式
    ThreadPool(int threadnum = num) : _threadnum(threadnum), _waitnum(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        cout << "ThreadPool Construct..." << endl;
    }
    // 初始化线程池
    void InitThreadPool()
    {
        // 构建出所有的线程，即只是调用线程的构造函数，但并不启动
        for (int i = 0; i < _threadnum; i++)
        {
            string name = "thread-" + to_string(i + 1);
            _threads.emplace_back(bind(&ThreadPool::HandlerTask, this, placeholders::_1), name);
            cout << "thread: " << name << " construct" << endl;
        }
    }
    // 启动线程池，线程开始启动工作函数HandlerTask
    void Start()
    {
        for (auto& thread : _threads)
        {
            thread.Start();
        }
    }
    // 线程池中线程的工作函数（这里使用了类之间的回调方法）
    void HandlerTask(string name) 
    {
        cout << name << " is running..." << endl;
        while (true)
        {
            LockQueue();
            // 任务队列中不一定有数据，需要循环等待任务
            while (_task_queue.empty())
            {
                _waitnum++;
                ThreadSleep();
                _waitnum--;
            }
            // 从任务队列中获取任务
            T t = _task_queue.front();
            _task_queue.pop();
            UnlockQueue();
            // 处理任务，这个任务属于线程独占的任务
            t();
            cout << "任务处理完毕" << endl;
        }
    }
    // 回收所有线程资源
    void Wait()
    {
        for (auto& thread : _threads)
        {
            thread.Join();
            cout << thread.name() << " is quit..." << endl;
        }
    }
    // 复制拷贝禁用
    ThreadPool<T> &operator=(const ThreadPool<T>&) = delete;
    ThreadPool(const ThreadPool<T>&) = delete;
public:
    // 单例模式(只有第一次会创建对象，后续都是获取该对象)
    static ThreadPool<T>* GetInstance()
    {
        if (nullptr == _instance) 
        {
            // 再次判断是为了防止多执行流阻塞在锁里以再次创建对象
            if (nullptr == _instance)
            {
                _instance = new ThreadPool<T>();
                _instance->InitThreadPool(); // 初始化
                _instance->Start(); // 启动
                cout << "创建线程池单例" << endl;
                return _instance;
            }
        }
        cout << "获取线程池单例" << endl;
        return _instance;
    }
    // 往任务队列中添加任务
    void Enqueue(const T& t)
    {
        // 线程此时可能在运行，这里需要申请锁保证线程安全
        LockQueue();
        _task_queue.push(t);
        // 此时任务队列中已有任务，需要唤醒线程进行处理
        if (_waitnum > 0)
        {
            ThreadWakeup();
        }
        cout << "enqueue task success" << endl;
        UnlockQueue();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        Wait();
    }

private:
    int _threadnum;          // 创建线程的数量
    vector<Thread> _threads; // 线程
    queue<T> _task_queue;    // 任务队列
    int _waitnum;            // 表示当前有多少线程在等待

    pthread_mutex_t _mutex;  
    pthread_cond_t _cond;   

    // 添加单例模式
    static ThreadPool<T>* _instance;
};

template <typename T>
ThreadPool<T>* ThreadPool<T>::_instance = nullptr;
